home *** CD-ROM | disk | FTP | other *** search
- /*
- * COMPARE - Perform a byte-by-byte comparison of two files
- * Copyright (C) 1993 Torsten Poulin
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- * The author can be contacted by s-mail at
- * Torsten Poulin
- * Banebrinken 99, 2, 77
- * DK-2400 Copenhagen NV
- * DENMARK
- *
- * $Id: Compare.c,v 37.5 93/06/21 08:33:41 Torsten Rel $
- * $Log: Compare.c,v $
- * Revision 37.5 93/06/21 08:33:41 Torsten
- * Now does its own buffering (32k per file) for increased throughput.
- *
- * Revision 37.4 93/03/01 13:16:42 Torsten
- * Fixed potentially dangerous bug: Input() could be closed.
- *
- * Revision 37.3 93/02/17 09:24:59 Torsten
- * Got rid of compiler warning caused by a forgotten '*' in
- * the cast used in MyPrintf(). Otherwise nothing is changed ;-)
- *
- * Revision 37.2 93/02/11 23:05:38 Torsten
- * Removed unnecessary #include.
- * Forgot to test the quiet flag before printing
- * the 'initial subsequence' messages. Fixed that.
- *
- * Revision 37.1 93/02/11 21:18:23 Torsten
- * This is the initial version.
- *
- */
-
- #include <exec/types.h>
- #include <exec/memory.h>
- #include <dos/dos.h>
- #include <dos/dostags.h>
- #include <clib/macros.h>
- #include <clib/exec_protos.h>
- #include <clib/dos_protos.h>
- #ifdef __SASC
- #include <pragmas/exec_pragmas.h>
- #include <pragmas/dos_pragmas.h>
- #endif
- #include "tastlib.h"
- #include "compare_rev.h"
-
- #define PROGNAME "Compare"
- #define TEMPLATE "FILE1,FILE2,SKIP1/N,SKIP2/N,QUIET/S"
- #define OPT_FILE1 0
- #define OPT_FILE2 1
- #define OPT_SKIP1 2
- #define OPT_SKIP2 3
- #define OPT_QUIET 4
- #define BUFLEN 32768L
-
- char const versionID[] = VERSTAG;
- char const copyright[] = "$COPYRIGHT:Copyright © 1993 Torsten Poulin$";
-
- typedef struct {
- struct DosLibrary *DOSBase;
- UBYTE buf1[BUFLEN];
- UBYTE buf2[BUFLEN];
- } Global;
-
- LONG Compare(BPTR, BPTR, BOOL, ULONG, ULONG, Global *);
-
- LONG entrypoint(VOID) {
- struct DosLibrary *DOSBase;
- struct RDArgs *args;
- Global *global;
- LONG arg[5];
- LONG rc = RETURN_OK;
- BPTR f1 = NULL, f2 = NULL;
- UBYTE *name1, *name2;
- ULONG skip1 = 0L, skip2 = 0L;
-
- if (!(DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 37L)))
- return RETURN_FAIL;
-
- if (!(global = AllocVec(sizeof(Global), MEMF_PUBLIC | MEMF_CLEAR)))
- rc = ERROR_NO_FREE_STORE;
- else {
- global->DOSBase = DOSBase;
-
- arg[OPT_FILE1] = arg[OPT_FILE2] = 0L;
- arg[OPT_SKIP1] = arg[OPT_SKIP2] = arg[OPT_QUIET] = 0L;
-
- if (!(args = ReadArgs(TEMPLATE, arg, NULL)))
- rc = RETURN_FAIL;
- else {
- name1 = (UBYTE *) arg[OPT_FILE1];
- name2 = (UBYTE *) arg[OPT_FILE2];
-
- if (!arg[OPT_FILE1])
- f1 = Input();
- else if (!(f1 = Open(name1, MODE_OLDFILE)))
- rc = RETURN_ERROR;
-
- if (!arg[OPT_FILE2]) {
- if (arg[OPT_FILE1])
- f2 = Input();
- else {
- /* Maybe I should print something more informative... */
- SetIoErr(ERROR_REQUIRED_ARG_MISSING);
- rc = RETURN_FAIL;
- }
- }
- else if (!(f2 = Open(name2, MODE_OLDFILE))) {
- if (arg[OPT_FILE1])
- Close(f1);
- rc = RETURN_ERROR;
- }
-
- if (arg[OPT_SKIP1])
- skip1 = *(LONG *) arg[OPT_SKIP1];
-
- if (arg[OPT_SKIP2])
- skip2 = *(LONG *) arg[OPT_SKIP2];
-
- if (f1 && f2) {
- rc = Compare(f1, f2, (BOOL) arg[OPT_QUIET], skip1, skip2, global);
- if (arg[OPT_FILE1])
- Close(f1);
- if (arg[OPT_FILE2])
- Close(f2);
- }
- FreeArgs(args);
- }
- FreeVec(global);
- }
- rc = printErrorMsg(rc, PROGNAME, DOSBase);
- CloseLibrary((struct Library *) DOSBase);
- return rc;
- }
-
-
- LONG Compare(BPTR f1, BPTR f2, BOOL quiet, ULONG skip1, ULONG skip2,
- Global *global)
- {
- struct DosLibrary *DOSBase = global->DOSBase;
- UBYTE *bufp1, *bufend1, *bufp2, *bufend2;
- LONG rlen1 = 0L, rlen2 = 0L;
- LONG c1, c2;
- ULONG lines = 1L, offset = 0L;
-
- bufp1 = bufend1 = global->buf1;
- bufp2 = bufend2 = global->buf2;
-
- while (skip1 -= rlen1) {
- if ((rlen1 = Read(f1, bufp1, MIN(skip1, BUFLEN))) <= 0) {
- if (rlen1 == 0)
- PutStr("Offset beyond end of FILE1\n");
- return RETURN_ERROR;
- }
- if (CheckSignal(SIGBREAKF_CTRL_C))
- return ERROR_BREAK;
- }
-
- while (skip2 -= rlen2) {
- if ((rlen2 = Read(f2, bufp2, MIN(skip2, BUFLEN))) <= 0) {
- if (rlen2 == 0)
- PutStr("Offset beyond end of FILE2\n");
- return RETURN_ERROR;
- }
- if (CheckSignal(SIGBREAKF_CTRL_C))
- return ERROR_BREAK;
- }
-
- for(;;) {
- if (bufp1 >= bufend1) {
- bufp1 = global->buf1;
- if ((rlen1 = Read(f1, bufp1, BUFLEN)) > 0)
- bufend1 = global->buf1 + rlen1;
- if (CheckSignal(SIGBREAKF_CTRL_C))
- return ERROR_BREAK;
- }
- c1 = *bufp1++;
-
- if (bufp2 >= bufend2) {
- bufp2 = global->buf2;
- if ((rlen2 = Read(f2, bufp2, BUFLEN)) > 0)
- bufend2 = global->buf2 + rlen2;
- if (CheckSignal(SIGBREAKF_CTRL_C))
- return ERROR_BREAK;
- }
- c2 = *bufp2++;
-
- if (rlen1 <= 0 || rlen2 <= 0)
- break; /* error or EOF */
-
- offset++;
-
- if (c1 != c2) {
- if (!quiet) {
- MyPrintf(global,
- "Files differ at offset %lu (hex 0x%lx), line %ld\n",
- offset, offset, lines);
- }
- SetIoErr(0L);
- return RETURN_WARN;
- }
-
- if (c1 == '\n')
- lines++;
- }
-
- if (rlen1 < 0 || rlen2 < 0)
- return RETURN_ERROR; /* An error occured while reading */
-
- if (rlen1 == 0 && rlen2 != 0) {
- if (!quiet)
- PutStr("FILE1 is an initial subsequence of FILE2\n");
- return RETURN_WARN;
- }
-
- if (rlen1 != 0 && rlen2 == 0) {
- if (!quiet)
- PutStr("FILE2 is an initial subsequence of FILE1\n");
- return RETURN_WARN;
- }
- return RETURN_OK;
- }
-